package com.irdstudio.efp.esb.api.rest.sed.repay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.irdstudio.basic.framework.core.constant.BaseConstant;
import com.irdstudio.basic.framework.core.constant.EsbEnums;
import com.irdstudio.basic.framework.core.constant.EsbRetCodeStandard;
import com.irdstudio.basic.framework.core.constant.SDicToLocalConstant;
import com.irdstudio.basic.framework.core.exception.BizException;
import com.irdstudio.basic.framework.core.util.*;
import com.irdstudio.basic.framework.core.util.sdic.SDicToLocal;
import com.irdstudio.efp.basic.framework.mq.client.producer.MQProducerMessageClient;
import com.irdstudio.efp.basic.framework.mq.constant.TagEnums;
import com.irdstudio.efp.basic.framework.mq.constant.TopicEnums;
import com.irdstudio.efp.console.common.ConsoleConstant;
import com.irdstudio.efp.console.service.facade.PubSysInfoService;
import com.irdstudio.efp.esb.api.bean.sed.repay.req.ReqActiRepayApplyBean;
import com.irdstudio.efp.esb.api.bean.sed.repay.req.ReqIntSetBean;
import com.irdstudio.efp.esb.api.common.EsbRespHandlerBean;
import com.irdstudio.efp.esb.api.common.EsbRespServiceBeanCreator;
import com.irdstudio.efp.esb.api.common.EsbRespServiceHandler;
import com.irdstudio.efp.esb.api.common.sed.SetlType;
import com.irdstudio.efp.esb.common.constant.EsbSysHeadEnums;
import com.irdstudio.efp.esb.common.server.req.EsbReqServiceBean;
import com.irdstudio.efp.esb.common.server.req.EsbReqSysHeadBean;
import com.irdstudio.efp.esb.common.server.resp.EsbRespServiceBean;
import com.irdstudio.efp.loan.service.facade.AccLoanService;
import com.irdstudio.efp.loan.service.facade.LoanRepayDetailService;
import com.irdstudio.efp.loan.service.vo.AccLoanVO;
import com.irdstudio.efp.loan.service.vo.LoanRepayDetailVO;
import com.irdstudio.efp.nls.common.constant.NlsApplyInfoEnums;
import com.irdstudio.efp.nls.common.constant.PrdAdaptedSoltEnums;
import com.irdstudio.efp.nls.common.constant.QueueTaskEnums;
import com.irdstudio.efp.nls.service.facade.queue.NlsProcessBizService;
import com.irdstudio.efp.nls.service.vo.queue.NlsProcessBizVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.common.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
* 普税贷产品对税e贷产品的此部分代码做了复用
* 说明：为了保证功能的复用性、提升开发的工作效率，对该代码进行了复用
* 评估是否会影响线上功能：否
* 评估时间：2020/5/25
* 处理方案：保留复用
*/
/**
 * 需求编号：【2019D0519】（业务提的需求编号）
 * 问题编号：【xxxxxxx】（若不是因为修复问题而新增该类，则留空）
 * 开发人员：qiuyf
 * 创建日期：2019年5月6日 上午11:10:03
 * 功能描述：主动还款申请接口
 */
@RestController
@RequestMapping("/esb")
public class ActiRepayApplyController {

	private static Logger logger = LoggerFactory.getLogger(ActiRepayApplyController.class);

	@ModelAttribute("esbReqServiceBean")
	public EsbReqServiceBean getReqEsbHeadBean(HttpServletRequest request) {
		logger.info("获取ESB请求对象，校验 ESB请求系统头和请求应用头对象开始");
		EsbReqServiceBean esbReqServiceBean = (EsbReqServiceBean) request.getAttribute("esbReqServiceBean");
		return esbReqServiceBean;
	}

	@ModelAttribute("reqActiRepayApplyBean")
	public ReqActiRepayApplyBean getReqEsbBodyBean(HttpServletRequest request) {
		logger.info("获取主动还款申请接口请求对象，校验主动还款申请接口请求体对象开始");
		String esbReqBody = (String) request.getAttribute("esbReqBody");
		return JSONObject.parseObject(esbReqBody, ReqActiRepayApplyBean.class);
	}

	@PostMapping("/SERVICE_30220002_02")
	public EsbRespServiceBean doRecv(@Validated @ModelAttribute("esbReqServiceBean") EsbReqServiceBean esbReqServiceBean, BindingResult br1,
									 @Validated @ModelAttribute("reqActiRepayApplyBean") ReqActiRepayApplyBean reqActiRepayApplyBean, BindingResult br2, Exception exception) {
		String globalSerno = esbReqServiceBean.getSysHead().getGlblSrlNo();
		String loanNo = reqActiRepayApplyBean.getDblNo();
		String loanRepayAplSeq = reqActiRepayApplyBean.getRpyAppFlowNo();
		TraceUtil.setTraceId(globalSerno);
		logger.info("主动还款申请接口处理开始----------还款申请流水号【" + loanRepayAplSeq + "】---------------借据号【" + loanNo + "】---------------");
		try {
			// 通过切面校验参数是否正确，如不正确则返回错误信息
			if (Objects.nonNull(exception)) {
				throw exception;
			}
			// 字段校验
			this.checkReqBean(reqActiRepayApplyBean);

			// 判断借据号是否存在借据信息，借据是否已结清
			AccLoanVO accLoanVO = this.checkAccLoan(loanNo);

			// 根据借据号查询是否存在在途的还款数据，存在则申请失败  【目前表示在途的状态有，处理中：01，挂起：05 】
			LoanRepayDetailVO loanRepayDetailVO = new LoanRepayDetailVO();
			loanRepayDetailVO.setLoanNo(loanNo);
			List<LoanRepayDetailVO> result = Optional.ofNullable(loanRepayDetailService.queryAllByLoanNo(loanRepayDetailVO)).orElseGet(ArrayList::new);

			boolean isOnWay = result.stream()
					//收集状态信息
					.map(LoanRepayDetailVO::getWfApprSts)
					//判断是否存在处理中 01，挂起：05
					.anyMatch(sts -> (NlsApplyInfoEnums.NlsApplyState.DEALING.getKey().equals(sts) || NlsApplyInfoEnums.NlsApplyState.HANG.getKey().equals(sts)));

			if (isOnWay) {
				throw new BizException(EsbRetCodeStandard.WFJKYWGZ.getValue(), "借据号【" + loanNo + "】，存在在途还款记录，还款失败！");
			}

			// 判断全局流水号是否已使用
			if (loanRepayDetailService.countInfoByGlobalSerno(globalSerno) > 0) {
				throw new BizException(EsbRetCodeStandard.WFJKYWGZ.getValue(), "全局流水号【" + globalSerno + "】已被使用！");
			}

			// 插入“处理中”还款数据
			LoanRepayDetailVO inLoanRepayDetailVO = this.insertData(reqActiRepayApplyBean, esbReqServiceBean.getSysHead(), accLoanVO);

			// 初始化网贷业务过程表
			int numNls = this.insertNlsProBiz(reqActiRepayApplyBean, accLoanVO);
			if (numNls < 0) {
				throw new BizException(EsbRetCodeStandard.SJCLYC.getValue(), "插入网贷业务过程表数据异常！");
			}

			// 投递mq
			producerService.sendMsg(new Message(TopicEnums.REPAY_QUEUE_TASK_TOPIC.getTopicId(), TagEnums.REPAY_TAG_QUEUE_TASK.getTagId(),
					loanRepayAplSeq, JSON.toJSONString(inLoanRepayDetailVO).getBytes("UTF-8")));

			return EsbRespServiceHandler.esbSuccessHandler(esbReqServiceBean);

		} catch (BizException e) {
			logger.error("***********调用主动还款申请接口处理失败**************还款申请流水号【+ loanRepayAplSeq +】**************借据号【+ loanNo +】**************" + e.getMessage());
			return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
					JSON.toJSONString(new EsbRespHandlerBean(e.getErrorCode(), e.getMessage())),
					EsbSysHeadEnums.RetStEnum.FAILURE.getCode(), e.getErrorCode(), e.getMessage());
		} catch (Exception e) {
			logger.error("***********调用主动还款申请接口处理失败**************还款申请流水号【+ loanRepayAplSeq +】**************借据号【+ loanNo +】**************" + e.getMessage());
			return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
					JSON.toJSONString(new EsbRespHandlerBean(EsbRetCodeStandard.OTHERS_EXCEPTION.getValue(), e.getMessage())),
					EsbSysHeadEnums.RetStEnum.FAILURE.getCode(), EsbRetCodeStandard.OTHERS_EXCEPTION.getValue(), e.getMessage());
		} finally {
			logger.info("主动还款申请接口处理结束----------还款申请流水号【" + loanRepayAplSeq + "】---------------借据号【" + loanNo + "】---------------");
			TraceUtil.clear();
		}
	}

	/**
	 * 请求报文字段校验、条件校验
	 *
	 * @author qiuyf
	 * @version 0.1 初始为0.1,后续变更则修改
	 * @since 2019年6月26日 下午7:46:11
	 */
	private void checkReqBean(ReqActiRepayApplyBean reqActiRepayApplyBean) throws BizException {
		// 还款类型
		String repayType = reqActiRepayApplyBean.getRpyType();
		MessageRuleCheckUtil.checkDate("还款日期", reqActiRepayApplyBean.getRpyDt(), "yyyy-MM-dd", EsbRetCodeStandard.JKYDCSJYBTG.getValue());
		MessageRuleCheckUtil.validateIdNo18(reqActiRepayApplyBean.getCertNo(), EsbRetCodeStandard.KHXXJYBTG.getValue());

		// RpyType ='06' TotRpyTerm有值 提前按期次还款时,总还款期数必输
		if (SetlType.SETL_TYPE_06.getType().equals(repayType) && StringUtil.isNullorBank(reqActiRepayApplyBean.getTotRpyTerm())) {
			logger.error("主动还款申请 申请流水号:【" + reqActiRepayApplyBean.getRpyAppFlowNo() + "】TotRpyTerm 提前按期次还款时,总还款期数必输! 【" + reqActiRepayApplyBean.getTotRpyTerm() + "】");
			throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), " 提前按期次还款时，总还款期数TotRpyTerm必输！");
		}

	}


	/**
	 * 校验借据号是否存在借据信息，借据是否已结清
	 *
	 * @author qiuyf
	 * @version 0.1 初始为0.1,后续变更则修改
	 * @since 2019年6月26日 下午7:15:15
	 */
	private AccLoanVO checkAccLoan(String loanNo) throws BizException {
		AccLoanVO accLoanVO = new AccLoanVO();
		accLoanVO.setBillNo(loanNo);
		accLoanVO = accLoanService.queryByPk(accLoanVO);
		if (Objects.isNull(accLoanVO)) {
			throw new BizException(EsbRetCodeStandard.WFJKYWGZ.getValue(), "根据借据号【" + loanNo + "】，查询到的借据信息为空！");
		}
		if (ConsoleConstant.ACC_STATUS_4.equals(accLoanVO.getAccountStatus())) {
			throw new BizException(EsbRetCodeStandard.WFJKYWGZ.getValue(), "借据号【" + loanNo + "】，借款已结清，无需再还款！");
		}
		return accLoanVO;
	}


	/**
	 * 插入还款计划明细表
	 *
	 * @author qiuyf
	 * @version 0.1 初始为0.1,后续变更则修改
	 * @since 2019年5月6日 下午2:04:04
	 */
	private LoanRepayDetailVO insertData(ReqActiRepayApplyBean reqActiRepayApplyBean, EsbReqSysHeadBean esbReqSysHeadBean, AccLoanVO accLoanVO) throws Exception {
		LoanRepayDetailVO loanRepayDetailVO = new LoanRepayDetailVO();
		//还款金额
		BigDecimal totalAmt = new BigDecimal(reqActiRepayApplyBean.getRpyAmt());
		//还款本金
		BigDecimal setlRemPrcpPaym = new BigDecimal(reqActiRepayApplyBean.getRpyPrin());

		/************************************************ 还款明细表数据来源于【渠道端】字段  ********************************************** start */
		//还款申请流水号
		loanRepayDetailVO.setSetlSeq(reqActiRepayApplyBean.getRpyAppFlowNo());
		//借据号
		loanRepayDetailVO.setLoanNo(reqActiRepayApplyBean.getDblNo());
		//证件类型
		loanRepayDetailVO.setIdType(reqActiRepayApplyBean.getCertTp());
		//证件号码
		loanRepayDetailVO.setIdNo(reqActiRepayApplyBean.getCertNo());
		//客户姓名
		loanRepayDetailVO.setCustName(reqActiRepayApplyBean.getCustNm());
		//还款类型
		loanRepayDetailVO.setSetlTyp(reqActiRepayApplyBean.getRpyType());
		/* 处理金额类型与结算金额  */
		loanRepayDetailVO = dealAmtAndType(loanRepayDetailVO, reqActiRepayApplyBean);
		//本次还款总计金额 = 还款金额
		loanRepayDetailVO.setTotalAmt(totalAmt);
		//归还欠本金额
		loanRepayDetailVO.setSetlOdPrcpAmt(setlRemPrcpPaym);
		// 执行利率
		loanRepayDetailVO.setIntRat(accLoanVO.getRealityIrY());
		//主动还款申请日期  = 还款日期
		loanRepayDetailVO.setSetlApplyDt(pubSysInfoService.getOpenday(BaseConstant.SYS_ID_1001));
		//还款期数 = 总还款期数
		if (StringUtils.isEmpty(reqActiRepayApplyBean.getTotRpyTerm())) {
			loanRepayDetailVO.setRepayTerm("0");
		} else {
			loanRepayDetailVO.setRepayTerm(reqActiRepayApplyBean.getTotRpyTerm());
		}
		//还款原因
		loanRepayDetailVO.setRepayReason(reqActiRepayApplyBean.getRpyRsn());
		//主动还款渠道 = 渠道号
		loanRepayDetailVO.setSetlOrigin(reqActiRepayApplyBean.getChanNo());
		//变更方式
		loanRepayDetailVO.setModifyMode(reqActiRepayApplyBean.getRpyPlanChgMd());
		ReqIntSetBean[] reqIntSetBeans = reqActiRepayApplyBean.getIntSetInfArry();
		if (null != reqIntSetBeans) {
			/**
			 * 以下字段在数组中是一致的，做校验
			 */
			for (ReqIntSetBean reqIntSetBean : reqIntSetBeans) {
				//结算账户分类
				loanRepayDetailVO.setSetlAcctClassify(reqIntSetBean.getBlgAcctCl());
				//还款模式 = 结算方式
				loanRepayDetailVO.setSetlMode(reqIntSetBean.getBlgMth());
				//账户类型 = 账户分类
				loanRepayDetailVO.setAcctTyp(reqIntSetBean.getAcctCtgry());
				//结算客户号
				loanRepayDetailVO.setCusNo(reqIntSetBean.getBlgCstNo());
				//还款账号  = 结算账号
				loanRepayDetailVO.setDisbAcNo(reqIntSetBean.getBlgAcctNo());
				//结算账户产品类型
				loanRepayDetailVO.setSetlAcctPrdType(reqIntSetBean.getBlgAcctProdType());
				//结算账户币种
				loanRepayDetailVO.setSetlCurr(SDicToLocal.getLocalSysDicVal(SDicToLocalConstant.CURRENCY, reqIntSetBean.getBlgAcctCurrCd()));
				//结算账户序号
				loanRepayDetailVO.setSetlAcctSeq(reqIntSetBean.getBlgAcctSrlNo());
				//自动锁定标记
				loanRepayDetailVO.setAtmLockMark(reqIntSetBean.getAtmLockMark());
				//贷款优先级
				loanRepayDetailVO.setLoanPrtyLvl(reqIntSetBean.getLoanPrtyLvl());
				//结算权重
				loanRepayDetailVO.setSetlWeight(reqIntSetBean.getBlgRto());
				//行内外标志
				loanRepayDetailVO.setBankInOut(reqIntSetBean.getBankInsdOutSdFlg());
			}
		} else {
			throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), "结算信息为空，还款申请失败。");
		}
		/********************************************** 还款明细表数据来源于【渠道端】字段 **********************************************  end */


		/** 还款明细表数据来源于【网贷系统表】字段 ----------- start */
		//放款金额 = acc_loan 借据金额
		loanRepayDetailVO.setDnAmt(null == accLoanVO.getLoanAmount() ? BigDecimal.ZERO : accLoanVO.getLoanAmount());
		/** 还款明细表数据来源于【网贷系统表】字段 ------------  end */


		/** ------------------- 其他赋值字段  start ---------------- */
		String sysDate = TimeUtil.getCurrentDate();
		//创建人
		loanRepayDetailVO.setSetlCreateUsr(BaseConstant.ADMIN);
		//创建日期
		loanRepayDetailVO.setSetlCreateDt(sysDate);
		//生效日期
		loanRepayDetailVO.setSetlValDt(pubSysInfoService.getOpenday(BaseConstant.SYS_ID_1001));
		//最新变更用户
		loanRepayDetailVO.setLastChgUsr(BaseConstant.ADMIN);
		//最新变更时间
		loanRepayDetailVO.setLastChgDt(TimeUtil.getCurrentDateTime());
		//全局流水号
		loanRepayDetailVO.setGlobalSerno(esbReqSysHeadBean.getGlblSrlNo());
		//合作平台id
		loanRepayDetailVO.setPlatfmId(esbReqSysHeadBean.getPlafmID());
		//合作平台用户id
		loanRepayDetailVO.setPlatfmUsrId(esbReqSysHeadBean.getPlafmUsrID());
		//审批状态设置为“处理中”
		loanRepayDetailVO.setWfApprSts(NlsApplyInfoEnums.NlsApplyState.DEALING.getKey());
		//插槽阶段为“还款 6”
		loanRepayDetailVO.setSoltStage(PrdAdaptedSoltEnums.PsdSoltStageEnum.REPAY.getVALUE());
		/** ------------------- 其他赋值字段  end   ---------------- */

		int num = loanRepayDetailService.insertLoanRepayDetail(loanRepayDetailVO);
		if (num < 0) {
			throw new BizException(EsbRetCodeStandard.SJCLYC.getValue(), "插入还款明细表数据异常！");
		}
		return loanRepayDetailVO;
	}

	/**
	 * 处理金额类型与结算金额
	 *
	 * @author qiuyf
	 * @version 0.1 初始为0.1,后续变更则修改
	 * @since 2019年6月13日 下午10:15:21
	 */
	private LoanRepayDetailVO dealAmtAndType(LoanRepayDetailVO loanRepayDetailVO, ReqActiRepayApplyBean reqActiRepayApplyBean) throws Exception {
		//结算信息数组
		ReqIntSetBean[] reqIntSetBeans = reqActiRepayApplyBean.getIntSetInfArry();
		StringBuffer setlTypeStr = new StringBuffer();
		if (null != reqIntSetBeans && reqIntSetBeans.length > 0) {
			for (ReqIntSetBean reqIntSetBean : reqIntSetBeans) {
				/*
					ALL-所有
					PRI-本金
					INT-利息
					ODI-复利
					ODP-罚息
					FEE-费用
				 */
				//金额类型
				String amtType = reqIntSetBean.getAmtType();
				setlTypeStr = setlTypeStr.append(amtType).append(",");
				//结算金额
				BigDecimal setlAmt = new BigDecimal(reqIntSetBean.getBlgAmt());
				if (EsbEnums.AmtType.ALL.getValue().equals(amtType)) {
					loanRepayDetailVO.setTotalAmt(setlAmt);
				} else if (EsbEnums.AmtType.PRINCIPAL.getValue().equals(amtType)) {
					loanRepayDetailVO.setSetlRemPrcpPaym(setlAmt);
				} else if (EsbEnums.AmtType.INTEREST.getValue().equals(amtType)) {
					//还款时总拖欠利息
					loanRepayDetailVO.setAllOdNormIntAmt(setlAmt);
					//归还欠息金额
					loanRepayDetailVO.setSetlOdNormInt(setlAmt);
				} else if (EsbEnums.AmtType.COMP_INTEREST.getValue().equals(amtType)) {
					//还款时总拖欠复利
					loanRepayDetailVO.setAllOdCommIntAmt(setlAmt);
					//归还复利金额
					loanRepayDetailVO.setSetlOdCommInt(setlAmt);
				} else if (EsbEnums.AmtType.DEF_INTEREST.getValue().equals(amtType)) {
					//还款时总拖欠罚息
					loanRepayDetailVO.setAllOdIntAmt(setlAmt);
					//归还罚息金额
					loanRepayDetailVO.setSetlOdIntAmt(setlAmt);
				} else if (EsbEnums.AmtType.FEE.getValue().equals(amtType)) {
					//还款时总拖欠费用
					loanRepayDetailVO.setAllOdFeeAmt(BigDecimal.ZERO);
					//归还费用总计
					loanRepayDetailVO.setSetlTotalFee(BigDecimal.ZERO);
				}
			}
		} else {
			throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), "结算信息为空，还款申请失败。");
		}
		loanRepayDetailVO.setAmtType(setlTypeStr.toString());
		return loanRepayDetailVO;
	}

	/**
	 * 初始化网贷业务过程表
	 *
	 * @author qiuyf
	 * @version 0.1 初始为0.1,后续变更则修改
	 * @since 2019年5月6日 下午2:16:06
	 */
	private int insertNlsProBiz(ReqActiRepayApplyBean reqActiRepayApplyBean, AccLoanVO accLoanVO) {
		NlsProcessBizVO inNlsProcessBizVo = new NlsProcessBizVO();
		//客户编号 
		inNlsProcessBizVo.setCusId(accLoanVO.getCusId());
		//产品ID
		inNlsProcessBizVo.setPrdId(accLoanVO.getPrdId());
		//产品代码 
		inNlsProcessBizVo.setPrdCode(accLoanVO.getPrdCode());
		//产品名称
		inNlsProcessBizVo.setPrdName(accLoanVO.getPrdName());
		//申请流水号 
		inNlsProcessBizVo.setApplySeq(reqActiRepayApplyBean.getRpyAppFlowNo());
		//客户名称 
		inNlsProcessBizVo.setCusName(reqActiRepayApplyBean.getCustNm());
		//挂起次数
		inNlsProcessBizVo.setHangTimes(QueueTaskEnums.QueueHangTimesEnum.INITIALIZE.getTimes());
		//创建时间
		inNlsProcessBizVo.setCreateTime(DateUtility.getCurrAppDateTimeString());
		//最后修改时间 
		inNlsProcessBizVo.setLastModifyTime(DateUtility.getCurrAppDateTimeString());
		//创建日期 
		inNlsProcessBizVo.setCreateDate(DateUtility.getCurrAppDateStr());
		//队列任务状态“待执行”
		inNlsProcessBizVo.setQueueTaskState(QueueTaskEnums.QueueTaskStateEnum.EXECUTORY.getCode());

		return nlsProcessBizService.insertNlsProcessBiz(inNlsProcessBizVo);
	}


	@Autowired
	@Qualifier("loanRepayDetailService")
	private LoanRepayDetailService loanRepayDetailService;

	@Autowired
	@Qualifier("accLoanService")
	private AccLoanService accLoanService;

	@Autowired
	@Qualifier("nlsProcessBizService")
	private NlsProcessBizService nlsProcessBizService;

	@Autowired
	@Qualifier("producerService")
	private MQProducerMessageClient producerService;

	@Autowired
	@Qualifier("pubSysInfoService")
	private PubSysInfoService pubSysInfoService;
}
